﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "QtCheckBoxGroup.h"
#include "GbmpNew.h"
#include "UiQtUtil.h"
#include "CheckBoxGroupDefinition.h"
#include <QCheckBox>
#include "IControlDefinitionChangeEventArgs.h"
#include "ControlDefinitionChangeEvent.h"
#include "QLayout.h"
#include <QVariant> 
#include "ControlDefinitionUtil.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

QtCheckBoxGroup::QtCheckBoxGroup(OwnerPtr<ICheckBoxGroupDefinition> pControlDefinition, QWidget* pParent)
    : QButtonGroup(pParent)
    , m_pControlDefinition(TransferOwnership(pControlDefinition))
    , m_pParent(pParent)
{
    if (!m_pControlDefinition || !pParent)
    {
        DBG_WARN(L"m_pControlDefinition或pParent是空指针",L"GDMPLab",L"2024-03-30");
        return;
    }

    setProperty(IS_DEFINITION, true);
    setExclusive(false);

    std::vector<const ICheckBoxDefinition*> checkBoxDefines = m_pControlDefinition->GetAllCheckBoxes();
    for (auto define : checkBoxDefines)
    {
        AddCheckBox(define);
    }

    connect<void(QButtonGroup::*)(QAbstractButton*)>(this, &QButtonGroup::buttonClicked, this, &QtCheckBoxGroup::OnButtonClicked);
    IControlDefinitionChangeEvent* pControlDefinitionChangeEvent = ControlDefinitionUtil::GetControlDefinitionChangeEvent(m_pControlDefinition.get());
    if (pControlDefinitionChangeEvent)
    {
        pControlDefinitionChangeEvent->Add(this);
    }
}

QtCheckBoxGroup::~QtCheckBoxGroup()
{
    IControlDefinitionChangeEvent* pControlDefinitionChangeEvent = ControlDefinitionUtil::GetControlDefinitionChangeEvent(m_pControlDefinition.get());
    if (pControlDefinitionChangeEvent)
    {
        pControlDefinitionChangeEvent->Delete(this);
    }
}

IControlDefinition* QtCheckBoxGroup::GetControlDefinition() const
{
    return const_cast<ICheckBoxGroupDefinition*>(m_pControlDefinition.get());
}

std::vector<QCheckBox*> QtCheckBoxGroup::GetAllControls() const
{
    return m_checkBoxControls;
}

void QtCheckBoxGroup::OnButtonClicked(QAbstractButton* pButton)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    QCheckBox* pCheckBox = qobject_cast<QCheckBox*>(pButton);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCheckBox, L"pCheckBox为空",L"GDMPLab",L"2024-03-30");
   
    std::wstring id = pCheckBox->objectName().toStdWString();
    CheckState checkState = UiQtUtil::GetCheckStateFrom(pCheckBox->checkState());

    // 修改Definition
    {
        ControlDefinitionChangeByUser changeByUser(m_pControlDefinition->GetId());// 用户操作导致
        m_pControlDefinition->SetCheckState(id, checkState);
    }
}

void gcmp::QtCheckBoxGroup::UpdateStatus()
{
    std::vector<QCheckBox*> checkBoxControls = this->GetAllControls();
    ICheckBoxGroupDefinition* pDefinition = dynamic_cast<ICheckBoxGroupDefinition*>(this->GetControlDefinition());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDefinition != nullptr, L"pDefinition为空",L"GDMPLab",L"2024-03-30");
    std::vector<const ICheckBoxDefinition*> checkBoxDefines = pDefinition->GetAllCheckBoxes();
    DBG_WARN_AND_RETURN_VOID_UNLESS(checkBoxControls.size() == checkBoxDefines.size(), L"数据有误",L"GDMPLab",L"2024-03-30");
    for (int i = 0; i < (int)checkBoxDefines.size(); ++i)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(checkBoxDefines[i] && checkBoxControls[i], L"checkBoxDefines[i] && checkBoxControls[i]为空",L"GDMPLab",L"2024-03-30");
        checkBoxControls[i]->setVisible(checkBoxDefines[i]->IsVisible());
        checkBoxControls[i]->setEnabled(checkBoxDefines[i]->IsEnabled());
    }
}

void gcmp::QtCheckBoxGroup::On(IControlDefinitionChangeEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    if (pArgs->GetType() == ControlDefinitionChangeEventType::Add)
    {
        OnControlDefinitionChangeEventTypeAdd(pArgs);
    }
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::Insert)
    {
        OnControlDefinitionChangeEventTypeInsert(pArgs);
    }
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::Delete)
    {
        std::vector<QCheckBox*> checkBoxVec = GetAllControls();
        int deleteControlDefinitionIndex = pArgs->GetDeleteOrInsertControlDefinitionIndex();
        DBG_WARN_AND_RETURN_VOID_UNLESS(deleteControlDefinitionIndex >= 0 && deleteControlDefinitionIndex < checkBoxVec.size(), L"deleteControlDefinitionIndex有误",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(checkBoxVec[deleteControlDefinitionIndex], L"iter为空",L"GDMPLab",L"2024-03-30");
        removeButton(checkBoxVec[deleteControlDefinitionIndex]);

        checkBoxVec[deleteControlDefinitionIndex]->deleteLater();

        auto indexDeleteIter = m_checkBoxControls.begin();
        std::advance(indexDeleteIter, deleteControlDefinitionIndex);
        m_checkBoxControls.erase(indexDeleteIter);
    }
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::DeleteAll)
    {
        for (auto iter : m_checkBoxControls)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(iter, L"iter为空",L"GDMPLab",L"2024-03-30");
            removeButton(iter);
            iter->deleteLater();
        }
        m_checkBoxControls.clear();
    }
    
    else if (pArgs->GetType() == ControlDefinitionChangeEventType::Other)
    {
        std::vector<QCheckBox*> checkBoxControls = GetAllControls();
        std::vector<const ICheckBoxDefinition*> checkBoxDefines = m_pControlDefinition->GetAllCheckBoxes();
        DBG_WARN_AND_RETURN_VOID_UNLESS(checkBoxControls.size() == checkBoxDefines.size(), L"数据有误",L"GDMPLab",L"2024-03-30");
        for (int i = 0; i < (int)checkBoxDefines.size(); ++i)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(checkBoxDefines[i] && checkBoxControls[i], L"checkBoxDefines[i] && checkBoxControls[i]为空",L"GDMPLab",L"2024-03-30");
            if (checkBoxControls[i]->checkState() != UiQtUtil::GetQtCheckStateFrom(checkBoxDefines[i]->GetCheckState()))
            {
                checkBoxControls[i]->setCheckState(UiQtUtil::GetQtCheckStateFrom(checkBoxDefines[i]->GetCheckState()));
            }
            if (checkBoxDefines[i]->IsVisible() != checkBoxControls[i]->isVisible())
            {
                checkBoxControls[i]->setVisible(checkBoxDefines[i]->IsVisible());
            }
            if (checkBoxDefines[i]->IsEnabled() != checkBoxControls[i]->isEnabled())
            {
                checkBoxControls[i]->setEnabled(checkBoxDefines[i]->IsEnabled());
            }
        }
    }
}

QCheckBox* gcmp::QtCheckBoxGroup::AddCheckBox(const ICheckBoxDefinition* pDefinition)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDefinition, L"pDefinition为空",L"GDMPLab",L"2024-03-30");
    QCheckBox* pCheckBox = CreateControl(pDefinition);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCheckBox, L"pCheckBox为空",L"GDMPLab",L"2024-03-30");

    addButton(pCheckBox);

    m_checkBoxControls.push_back(pCheckBox);

    return pCheckBox;
}

QCheckBox* gcmp::QtCheckBoxGroup::CreateControl(const ICheckBoxDefinition* pDefinition)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_pParent, L"m_pParent为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDefinition, L"pDefinition为空",L"GDMPLab",L"2024-03-30");

    QCheckBox* pCheckBox = NEW_AS_QT_CHILD(QCheckBox, QString::fromStdWString(pDefinition->GetCaption()), m_pParent);
    pCheckBox->setProperty(IS_DEFINITION, true);
    pCheckBox->setObjectName(QString::fromStdWString(pDefinition->GetId()));
    pCheckBox->setToolTip(QString::fromStdWString(pDefinition->GetTooltip()));
    pCheckBox->setCheckState(UiQtUtil::GetQtCheckStateFrom(pDefinition->GetCheckState()));
    pCheckBox->setVisible(pDefinition->IsVisible());
    pCheckBox->setEnabled(pDefinition->IsEnabled());
    return pCheckBox;
}

void gcmp::QtCheckBoxGroup::OnControlDefinitionChangeEventTypeInsert(IControlDefinitionChangeEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    //1.移出QButtonGroup所有控件
    std::vector<QCheckBox*> checkBoxControls = GetAllControls();
    for (auto iter : checkBoxControls)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(iter, L"iter为空",L"GDMPLab",L"2024-03-30");
        removeButton(iter);
    }
    //2.根据插入的define创建对应的控件
    const ICheckBoxDefinition* pDefinition = dynamic_cast<const ICheckBoxDefinition*>(pArgs->GetControlDefinition());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDefinition, L"pDefinition为空",L"GDMPLab",L"2024-03-30");
    QCheckBox* pCheckBoxControl = CreateControl(pDefinition);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCheckBoxControl, L"pCheckBoxControl为空",L"GDMPLab",L"2024-03-30");

    int insertControlDefinitionIndex = pArgs->GetDeleteOrInsertControlDefinitionIndex();
    DBG_WARN_AND_RETURN_VOID_UNLESS(insertControlDefinitionIndex >= 0 && insertControlDefinitionIndex < checkBoxControls.size(), L"insertControlDefinitionIndex有误",L"GDMPLab",L"2024-03-30");

    //3.往m_parent插入对应的控件
    QLayout * pLayout = m_pParent->layout();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLayout, L"pLayout为空",L"GDMPLab",L"2024-03-30");
    int index = pLayout->indexOf(checkBoxControls[insertControlDefinitionIndex]);
    QBoxLayout* pQBoxLayout = dynamic_cast<QBoxLayout*>(pLayout);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pQBoxLayout, L"pQBoxLayout为空",L"GDMPLab",L"2024-03-30");
    pQBoxLayout->insertWidget(index, pCheckBoxControl);

    //4.往m_checkBoxControls中插入对应的控件
    auto indexInsertIter = m_checkBoxControls.begin();
    std::advance(indexInsertIter, insertControlDefinitionIndex);
    m_checkBoxControls.insert(indexInsertIter, pCheckBoxControl);

    //5.添加m_checkBoxControls所有控件到QButtonGroup
    for (auto iter : m_checkBoxControls)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(iter, L"iter为空",L"GDMPLab",L"2024-03-30");
        addButton(iter);
    }
}

void gcmp::QtCheckBoxGroup::OnControlDefinitionChangeEventTypeAdd(IControlDefinitionChangeEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pParent, L"m_pParent为空",L"GDMPLab",L"2024-03-30");
          
    QLayout * pLayout = m_pParent->layout();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLayout, L"pLayout为空",L"GDMPLab",L"2024-03-30");
    QCheckBox* pCheckBoxRef = m_checkBoxControls.back();
    int index = pLayout->indexOf(pCheckBoxRef);

    const ICheckBoxDefinition* pCheckBoxDefine = dynamic_cast<const ICheckBoxDefinition*>(pArgs->GetControlDefinition());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCheckBoxDefine, L"pCheckBoxDefine为空",L"GDMPLab",L"2024-03-30");
    QCheckBox* pControl = AddCheckBox(pCheckBoxDefine);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pControl, L"pControl为空",L"GDMPLab",L"2024-03-30");
    
    QBoxLayout* pQBoxLayout = dynamic_cast<QBoxLayout*>(pLayout);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pQBoxLayout, L"pQBoxLayout为空",L"GDMPLab",L"2024-03-30");

    pQBoxLayout->insertWidget(index + 1, pControl);
}
